// 设置验证服务
// 提供设置值的验证功能

import { BaseSetting, SettingValidationResult, SettingType } from '../types/settings';

export class SettingsValidator {
  // 验证单个设置
  static validateSetting(setting: BaseSetting, value: any): SettingValidationResult {
    const errors: string[] = [];
    const warnings: string[] = [];

    // 基础类型验证
    if (!this.validateType(setting.type, value)) {
      errors.push(`值类型不匹配，期望 ${setting.type} 类型`);
      return { isValid: false, errors, warnings };
    }

    // 必填验证
    if (setting.validation?.required && (value === null || value === undefined || value === '')) {
      errors.push('此设置为必填项');
    }

    // 数值范围验证
    if (setting.type === SettingType.Number && typeof value === 'number') {
      if (setting.validation?.min !== undefined && value < setting.validation.min) {
        errors.push(`值不能小于 ${setting.validation.min}`);
      }
      if (setting.validation?.max !== undefined && value > setting.validation.max) {
        errors.push(`值不能大于 ${setting.validation.max}`);
      }
    }

    // 字符串长度验证
    if (setting.type === SettingType.String && typeof value === 'string') {
      if (setting.validation?.min !== undefined && value.length < setting.validation.min) {
        errors.push(`长度不能少于 ${setting.validation.min} 个字符`);
      }
      if (setting.validation?.max !== undefined && value.length > setting.validation.max) {
        errors.push(`长度不能超过 ${setting.validation.max} 个字符`);
      }
    }

    // 正则表达式验证
    if (setting.validation?.pattern && typeof value === 'string') {
      const regex = new RegExp(setting.validation.pattern);
      if (!regex.test(value)) {
        errors.push('值格式不正确');
      }
    }

    // 选项验证
    if (setting.validation?.options && setting.type === SettingType.Select) {
      const validOptions = setting.validation.options.map(opt => opt.value);
      if (!validOptions.includes(value)) {
        errors.push('请选择有效的选项');
      }
    }

    // 多选验证
    if (setting.validation?.options && setting.type === SettingType.MultiSelect) {
      if (Array.isArray(value)) {
        const validOptions = setting.validation.options.map(opt => opt.value);
        const invalidValues = value.filter(v => !validOptions.includes(v));
        if (invalidValues.length > 0) {
          errors.push(`包含无效选项: ${invalidValues.join(', ')}`);
        }
      } else {
        errors.push('多选值必须是数组');
      }
    }

    // 颜色值验证
    if (setting.type === SettingType.Color && typeof value === 'string') {
      if (!this.isValidColor(value)) {
        errors.push('请输入有效的颜色值');
      }
    }

    // 快捷键验证
    if (setting.type === SettingType.Shortcut && typeof value === 'string') {
      if (!this.isValidShortcut(value)) {
        errors.push('请输入有效的快捷键组合');
      }
    }

    // 自定义验证
    if (setting.validation?.custom) {
      const customError = setting.validation.custom(value);
      if (customError) {
        errors.push(customError);
      }
    }

    // 特定设置的业务逻辑验证
    this.validateBusinessLogic(setting, value, warnings);

    return {
      isValid: errors.length === 0,
      errors,
      warnings
    };
  }

  // 类型验证
  private static validateType(expectedType: SettingType, value: any): boolean {
    switch (expectedType) {
      case SettingType.Boolean:
        return typeof value === 'boolean';
      case SettingType.Number:
        return typeof value === 'number' && !isNaN(value);
      case SettingType.String:
      case SettingType.Select:
      case SettingType.Color:
      case SettingType.Shortcut:
      case SettingType.Font:
        return typeof value === 'string';
      case SettingType.MultiSelect:
        return Array.isArray(value);
      default:
        return true;
    }
  }

  // 颜色值验证
  private static isValidColor(color: string): boolean {
    // 支持十六进制颜色 (#RGB, #RRGGBB)
    const hexPattern = /^#([A-Fa-f0-9]{3}|[A-Fa-f0-9]{6})$/;
    if (hexPattern.test(color)) {
      return true;
    }

    // 支持RGB/RGBA
    const rgbPattern = /^rgba?\(\s*\d+\s*,\s*\d+\s*,\s*\d+\s*(,\s*[\d.]+)?\s*\)$/;
    if (rgbPattern.test(color)) {
      return true;
    }

    // 支持HSL/HSLA
    const hslPattern = /^hsla?\(\s*\d+\s*,\s*\d+%\s*,\s*\d+%\s*(,\s*[\d.]+)?\s*\)$/;
    if (hslPattern.test(color)) {
      return true;
    }

    // 支持CSS颜色名称
    const cssColors = [
      'red', 'green', 'blue', 'white', 'black', 'yellow', 'orange', 'purple',
      'pink', 'brown', 'gray', 'grey', 'cyan', 'magenta', 'lime', 'navy',
      'teal', 'silver', 'maroon', 'olive', 'aqua', 'fuchsia'
    ];
    return cssColors.includes(color.toLowerCase());
  }

  // 快捷键验证
  private static isValidShortcut(shortcut: string): boolean {
    if (!shortcut.trim()) return false;

    const parts = shortcut.split('+').map(part => part.trim());
    if (parts.length === 0) return false;

    // 检查修饰键
    const modifiers = ['Ctrl', 'Shift', 'Alt', 'Meta', 'Cmd'];
    const validModifiers = parts.slice(0, -1).every(part => 
      modifiers.includes(part)
    );

    // 检查主键
    const mainKey = parts[parts.length - 1];
    const validMainKey = mainKey.length === 1 || // 单字符
      ['F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9', 'F10', 'F11', 'F12',
       'Tab', 'Enter', 'Escape', 'Space', 'Backspace', 'Delete', 'Home', 'End',
       'PageUp', 'PageDown', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(mainKey);

    return validModifiers && validMainKey;
  }

  // 业务逻辑验证
  private static validateBusinessLogic(setting: BaseSetting, value: any, warnings: string[]): void {
    switch (setting.id) {
      case 'editor.fontSize':
        if (typeof value === 'number') {
          if (value < 10) {
            warnings.push('字体过小可能影响阅读体验');
          } else if (value > 24) {
            warnings.push('字体过大可能影响代码显示');
          }
        }
        break;

      case 'advanced.maxMemoryUsage':
        if (typeof value === 'number') {
          if (value < 512) {
            warnings.push('内存限制过低可能影响性能');
          } else if (value > 4096) {
            warnings.push('内存限制过高可能影响系统稳定性');
          }
        }
        break;

      case 'editor.tabSize':
        if (typeof value === 'number') {
          if (value > 8) {
            warnings.push('制表符大小过大可能影响代码格式');
          }
        }
        break;

      case 'appearance.windowOpacity':
        if (typeof value === 'number') {
          if (value < 0.8) {
            warnings.push('窗口透明度过低可能影响可读性');
          }
        }
        break;
    }
  }

  // 批量验证设置
  static validateSettings(settings: Record<string, BaseSetting>, values: Record<string, any>): Record<string, SettingValidationResult> {
    const results: Record<string, SettingValidationResult> = {};

    Object.entries(settings).forEach(([settingId, setting]) => {
      const value = values[settingId];
      results[settingId] = this.validateSetting(setting, value);
    });

    return results;
  }

  // 检查快捷键冲突
  static checkShortcutConflicts(shortcuts: Record<string, string>): Record<string, string[]> {
    const conflicts: Record<string, string[]> = {};
    const shortcutMap: Record<string, string[]> = {};

    // 构建快捷键映射
    Object.entries(shortcuts).forEach(([actionId, shortcut]) => {
      if (!shortcutMap[shortcut]) {
        shortcutMap[shortcut] = [];
      }
      shortcutMap[shortcut].push(actionId);
    });

    // 检查冲突
    Object.entries(shortcutMap).forEach(([shortcut, actionIds]) => {
      if (actionIds.length > 1) {
        actionIds.forEach(actionId => {
          conflicts[actionId] = actionIds.filter(id => id !== actionId);
        });
      }
    });

    return conflicts;
  }

  // 获取设置建议值
  static getSuggestedValue(setting: BaseSetting, currentValue: any): any {
    // 根据设置类型和当前值提供建议
    switch (setting.id) {
      case 'editor.fontSize':
        if (typeof currentValue === 'number') {
          if (currentValue < 10) return 12;
          if (currentValue > 24) return 18;
        }
        break;

      case 'editor.tabSize':
        if (typeof currentValue === 'number' && currentValue > 8) {
          return 4;
        }
        break;

      case 'appearance.windowOpacity':
        if (typeof currentValue === 'number' && currentValue < 0.5) {
          return 0.9;
        }
        break;
    }

    return currentValue;
  }
}
